package com.qf.hospital.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.qf.hospital.constants.HospitalConstants;
import com.qf.hospital.entity.SysMenu;
import com.qf.hospital.entity.SysRole;
import com.qf.hospital.entity.User;
import com.qf.hospital.entity.UserExample;
import com.qf.hospital.enums.HospitalErrorEnums;
import com.qf.hospital.exception.HospitalException;
import com.qf.hospital.mapper.SysUserMapper;
import com.qf.hospital.realm.HospitalRealm;
import com.qf.hospital.service.SysRoleService;
import com.qf.hospital.service.UserService;
import com.qf.hospital.util.ExampleUtil;
import com.qf.hospital.vo.SideVO;
import com.qf.hospital.vo.UserRoleVO;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author Administrator
 * @version V1.0
 * @Project hospital
 * @Package com.qf.hospital.service.impl
 * @Description: ${TODO}
 * @Date 2021/10/15 15:04
 */

@Service
public class UserServiceImpl implements UserService {

    private Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    private final String INIT_PASSWORD = "123456789abc!";

    @Autowired
    private SysUserMapper userMapper;

    @Autowired
    private SysRoleService sysRoleService;

    /**
     * 根据用户名查询用户信息
     * @param loginname
     * @return
     */
    @Override
    public User findByName(String loginname) {
        //1. 准备example设置条件
        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        //2. 设置查询条件
        criteria.andLoginNameEqualTo(loginname);
        //3. 执行查询
        List<User> list = userMapper.selectByExample(example);
        //4. 返回
        if (list != null && list.size() == 1){
            User user = list.get(0);
            if (user.getAvailable() == 0){
                //用户已经失效
                log.info("【登录功能】 用户已经失效，请联系管理员");
                throw new HospitalException(HospitalErrorEnums.USER_HAS_EXPIRED);
            }
            return user;
        }
        return null;
    }

    /**
     * 根据用户Id查询菜单信息
     * @param userId
     * @return
     */
    @Override
    public List<SideVO> findSideByUserId(Integer userId) {
        //1.根据userId查询菜单信息
        List<SysMenu> menuList = userMapper.findMenuByUserId(userId);
        //2.封装数据
        List<SideVO> result = new ArrayList<>();
        Map<Integer,SideVO> oneLevelMenu = new HashMap<>();

        //2.1 从menuList筛选出所有parentId = 1的以及菜单，并且封装到List集合
        ListIterator<SysMenu> menuListIterator = menuList.listIterator();
        while (menuListIterator.hasNext()){
            SysMenu menu = menuListIterator.next();
            if (menu.getParentId() == 1){
                // 一级菜单
                SideVO vo = new SideVO();
                BeanUtils.copyProperties(menu, vo);
                oneLevelMenu.put(vo.getId(), vo);
                menuListIterator.remove();
            }
        }
        //2.2 从menuList中找到二级菜单，并且将二级菜单封装到指定的一级菜单的children属性中
        for (SysMenu sysMenu : menuList) {
            SideVO parentSideVO = oneLevelMenu.get(sysMenu.getParentId());
            if (parentSideVO != null){
                SideVO childVO = new SideVO();
                BeanUtils.copyProperties(sysMenu, childVO);
                parentSideVO.getChildren().add(childVO);
            }
        }
        //2.3 将Map集合中的数据，都封装到result的list集合中
        for (Map.Entry<Integer, SideVO> entry : oneLevelMenu.entrySet()) {
            result.add(entry.getValue());
        }
        //3.返回
        return result;
    }

    @Override
    public PageInfo<User> findAll(String realname, String loginname, String address, String phone, String identity, Integer page, Integer limit) {
        //1. 执行分页
        PageHelper.startPage(1, 5);

        //2. 封装查询条件
        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();

        //2.1 真实姓名
        if(!StringUtils.isEmpty(realname)){
            criteria.andRealNameLike(ExampleUtil.any(realname));
        }
        //2.2 登录名
        if (!StringUtils.isEmpty(loginname)){
            criteria.andLoginNameLike(ExampleUtil.any(loginname));
        }
        //2.3 地址
        if(!StringUtils.isEmpty(address)){
            criteria.andAddressLike(ExampleUtil.any(address));
        }
        //2.4 手机号
        if (!StringUtils.isEmpty(phone)){
            criteria.andPhoneLike(ExampleUtil.any(phone));
        }
        //2.5 身份证
        if (!StringUtils.isEmpty(identity)){
            criteria.andIdentityLike(identity);
        }
        //3.执行查询
        List<User> userList = userMapper.selectByExample(example);
        //4.封装PageInfo
        PageInfo<User> pageInfo = new PageInfo<>(userList);
        //5.返回
        return pageInfo;
    }

    @Override
    @Transactional
    public void addUser(User user) {
        //1. 封装数据 pwd，salt，type（默认值为2，系统用户）
        //1.1 生成盐
        String salt = UUID.randomUUID().toString();
        //1.2 生成密码
        String pwd = new Md5Hash(INIT_PASSWORD,salt, HospitalRealm.HASH_ITERATIONS).toString();
        //1.3生成用户类型
        Integer type = HospitalConstants.USER_TYPE_SYSTEM;
        //1.4设置到User中
        user.setSalt(salt);
        user.setPwd(pwd);
        user.setType(type);
        //2.执行添加
        int count = userMapper.insertSelective(user);

        //3. 健壮性判断
        if (count != 1){
            log.error("【添加用户信息】 添加失败 user = {} ",user);
            throw new HospitalException(HospitalErrorEnums.USER_ADD_ERROR);
        }
    }

    @Override
    public List<UserRoleVO> initUserRole(Integer userid) {

        //1. 查询全部角色信息
        List<SysRole> roleList = sysRoleService.findAll();
        //2. 查询当前用户拥有的角色id
        List<Integer> roleIdList = userMapper.findRoleByUserId(userid);

        //3. 根据上述结果，封装UserRoleVO
        List<UserRoleVO> data = new ArrayList<>();

        for (SysRole sysRole : roleList) {
            UserRoleVO vo = new UserRoleVO();
            BeanUtils.copyProperties(sysRole, vo);
            if (roleIdList.contains(vo.getRoleId())){
                vo.setLayChecked(true);
            }
            data.add(vo);
        }
        //4. 返回
        return data;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void saveUserRole(Integer userid, Integer[] ids) {
        //1.先删除
        userMapper.deleteRoleByUserId(userid);
        //2.再添加角色
        if (ids != null && ids.length > 0){
            int count = userMapper.saveUserRole(userid,ids);
            if (count != ids.length){
                log.error("【分配角色信息】 分配角色信息失败 userId = {},roleIds = {}",userid,Arrays.toString(ids));
                throw new HospitalException(HospitalErrorEnums.USER_SAVE_ROLE_ERROR);
            }
        }
    }

    @Override
    @Transactional
    public void deleteByUserId(Integer userid) {
       int count = userMapper.updateAvailabeByUserId(userid);
        if (count != 1){
            log.error("【删除用户信息】 删除失败 userid = {}",userid );
            throw new HospitalException(HospitalErrorEnums.USER_DELETE_ERROR);
        }
    }

    @Override
    @Transactional
    public void resetPwdByUserId(Integer userid) {
        int count = userMapper.updatePwdByUserId(userid);
        if (count != 1){
            log.error("【修改密码】 修改密码失败 userid = {}",userid);
            throw new HospitalException(HospitalErrorEnums.USER_UPDATE_ERROR);
        }
    }

    @Override
    @Transactional
    public int updateByUserId(User user) {
        return userMapper.updateByPrimaryKey(user);
//        int count = userMapper.updateByPrimaryKeySelective(user);
//        if (count != 1){
//            log.error("【修改信息】 修改信息失败 user = #{}",user);
//            throw new HospitalException(HospitalErrorEnums.USER_UPDATE_ROLE_ERROR);
//        }
    }
}
